/*
 * options.cpp
 *
 *  Created on: Jul 23, 2015
 *      Author: lion
 */

#include "v8/src/flags/flags.h"

#include "version.h"
#include "console.h"
#include "path.h"
#include "Fiber.h"
#include "options.h"
#include "unicode/locid.h"
#include "unicode/timezone.h"

namespace fibjs {

#if ARCH_BITS == 64
int32_t stack_size = 512;
#else
int32_t stack_size = 256;
#endif

bool g_prof = false;
int32_t g_prof_interval = 1000;

FILE* g_cov = nullptr;

bool g_tcpdump = false;
bool g_ssldump = false;
bool g_pipedump = false;
bool g_no_deprecation = false;

bool g_uv_socket = false;

bool g_track_native_object = false;

bool g_openssl_legacy_provider = false;

bool g_sync_console = false;

exlib::string g_exec_code;

#ifdef DEBUG
#define GUARD_SIZE 32
#else
#define GUARD_SIZE 16
#endif

static void printHelp()
{
    puts("Usage: fibjs [options] [script.js] [arguments] \n"
         "\n"
         "Options:\n"
         "  -h, --help                  print fibjs command line options.\n"
         "  -v, --version               print fibjs version.\n"
         "\n"
         "  -e code                     evaluate script\n"
         "\n"
         "  --use-thread                run fibjs in thread mode.\n"
         "  --no-deprecation            silence deprecation warnings.\n"
         "  --sync-console              use synchronous console output instead of async.\n"
         "  --tcpdump                   print out the contents of the tcp package.\n"
         "  --ssldump                   print out the contents of the ssl package.\n"
         "  --pipedump                  print out the contents of the pipe package.\n"
         "\n"
         "  --use-uv-socket[=on|off]\n"
         "                              use uv as socket backend.\n"
         "\n"
         "  --init                      write a package.json file.\n"
         "  --install [opt] foo         install the dependencies in the local node_modules folder.\n"
         "    -S, --save                save package config to dependencies.\n"
         "    -D, --save-dev            save package config to devDependencies.\n"
         "    --target                  specify the path of the package.json file.\n"
         "\n"
         "  --openssl-legacy-provider   enable OpenSSL 3.0 legacy provider.\n"
         "\n"
         "  --prof                      log statistical profiling information.\n"
         "  --prof-interval=n           interval for --prof samples (in microseconds, default: 1000).\n"
         "  --prof-process              process log file generated by profiler.start.\n"
         "  --track-native-object       track native object counts.\n"
         "\n"
         "  --cov[=filename]            collect code coverage information (only work on the main Worker).\n"
         "  --cov-process               generate code coverage analysis report.\n"
         "\n"
         "  --v8-options                print v8 command line options.\n"
         "\n"
         "Documentation can be found at http://fibjs.org\n");
}

void options(int32_t& pos, char* argv[])
{
    int32_t i;
    int32_t df = 0;

    for (i = 1; i < pos; i++) {
        char* arg = argv[i];

        if (df)
            argv[i - df] = arg;

        if (arg[0] != '-')
            break;
        else if (arg[1] == '-') {
            int32_t j;
            exlib::string tmp("opt_tools/");
            tmp += arg + 2;

            for (j = 0; opt_tools[j].name && qstrcmp(opt_tools[j].name, tmp.c_str()); j++)
                ;

            if (opt_tools[j].name)
                break;
        }

        if (!qstrcmp(arg, "--help") || !qstrcmp(arg, "-h")) {
            printHelp();
            _exit(0);
        } else if (!qstrcmp(arg, "--version") || !qstrcmp(arg, "-v")) {
            printf("v%s\n", fibjs_version);
            _exit(0);
        } else if (!qstrcmp(arg, "--use-thread")) {
            exlib::Service::use_thread = true;
            df++;
        } else if (!qstrcmp(arg, "--no-deprecation")) {
            g_no_deprecation = true;
            df++;
        } else if (!qstrcmp(arg, "--sync-console")) {
            g_sync_console = true;
            df++;
        } else if (!qstrcmp(arg, "--tcpdump")) {
            g_tcpdump = true;
            df++;
        } else if (!qstrcmp(arg, "--ssldump")) {
            g_ssldump = true;
            df++;
        } else if (!qstrcmp(arg, "--pipedump")) {
            g_pipedump = true;
            df++;
        } else if (!qstrcmp(arg, "--use-uv-socket", 15)) {
            g_uv_socket = (arg[15] == 0 || !qstrcmp(arg + 15, "=on"));
            df++;
        } else if (!qstrcmp(arg, "--prof")) {
            g_prof = true;
            df++;
        } else if (!qstrcmp(arg, "--prof-interval=", 16)) {
            g_prof_interval = atoi(arg + 16);
            if (g_prof_interval < 50)
                g_prof_interval = 50;
            df++;
        } else if (!qstrcmp(arg, "--track-native-object")) {
            g_track_native_object = true;
            df++;
        } else if (!qstrcmp(arg, "--openssl-legacy-provider")) {
            g_openssl_legacy_provider = true;
            df++;
        } else if (!qstrcmp(arg, "--cov=", 6)) {
            g_cov = fopen(arg + 6, "a");
            if (g_cov == nullptr) {
                printf("Invalid filename: %s\n", arg + 6);
                _exit(0);
            }
            df++;
        } else if (!qstrcmp(arg, "--cov")) {
            char name[22];
            date_t d;
            d.now();
            snprintf(name, sizeof(name), "fibjs-%d.lcov", (int32_t)d.date());
            g_cov = fopen(name, "a");
            if (g_cov == nullptr) {
                printf("Can't open file: %s, please try again", name);
                _exit(0);
            }
            df++;
        } else if (!qstrcmp(arg, "-e")) {
            if (i + 1 < pos) {
                g_exec_code = argv[i + 1];
                i++;
                df += 2;
            }
        } else if (!qstrcmp(arg, "--v8-options")) {
            v8::internal::FlagList::PrintHelp();
            _exit(0);
        }
    }

    pos = i;
    int32_t argc = pos - df;

    v8::V8::SetFlagsFromCommandLine(&argc, argv, true);

    char* lang = getenv("LANG");
    if (lang) {
        icu::Locale locale(lang);
        UErrorCode error_code = U_ZERO_ERROR;
        icu::Locale::setDefault(locale, error_code);
    }

    char* tz = getenv("TZ");
    if (tz) {
        icu::TimeZone* zone = icu::TimeZone::createTimeZone(tz);
        icu::TimeZone::setDefault(*zone);
    }

    size_t sz = uv_get_total_memory() / 1024 / 1024;
    sz = sz * 3 / 4;

    // Disable lazy compilation and force eager compilation
    v8::internal::v8_flags.lazy = false;
    v8::internal::v8_flags.lazy_eval = false;
    v8::internal::v8_flags.max_lazy = false;
    
    // Disable lazy source positions to avoid source code dependency
    v8::internal::v8_flags.enable_lazy_source_positions = false;
    v8::internal::v8_flags.stress_lazy_source_positions = false;
    
    // Disable lazy feedback allocation
    v8::internal::v8_flags.lazy_feedback_allocation = false;

    v8::internal::v8_flags.max_heap_size = sz;
    v8::internal::v8_flags.stack_size = stack_size - GUARD_SIZE;
    v8::internal::v8_flags.wasm_code_gc = false;

    v8::internal::v8_flags.turbo_store_elimination = false;

    // v8::internal::v8_flags.harmony_import_assertions = false;
    v8::internal::v8_flags.harmony_import_attributes = true;

    v8::internal::v8_flags.expose_gc = true;
}
}
